package com.ffcs.crmd.tsp.client.core;

import org.slf4j.Logger;

import com.ffcs.crmd.tsp.api.dto.heart.HeartbeatData;
import com.ffcs.crmd.tsp.api.dto.netty.RemotingCommand;
import com.ffcs.crmd.tsp.api.netty.INettyConfigClient;
import com.ffcs.crmd.tsp.api.netty.INettyRemotingClient;
import com.ffcs.crmd.tsp.client.log.ClientLogger;
import com.ffcs.crmd.tsp.client.netty.NettyRemotingClient;
import com.ffcs.crmd.tsp.common.constant.LoggerName;
import com.ffcs.crmd.tsp.common.exception.TspRemotingException;
import com.ffcs.crmd.tsp.common.netty.RequestCode;
import com.ffcs.crmd.tsp.common.netty.RequestResult;
import com.ffcs.crmd.tsp.common.netty.ResponseCode;
import com.ffcs.crmd.tsp.common.netty.enu.NettyRequestResult;
import com.ffcs.crmd.tsp.core.util.XmlUtil;

/**
 * 
 * 功能说明:客户端通信服务实现
 *
 * @author ZHONGFUHUA
 * 
 * @since 1.0.0-SNAPSHOT
 *
 */
public class TspClientImpl {

    /**
     * 日志
     */
    private static final Logger  LOG = ClientLogger.getLogger(LoggerName.RemotingLoggerName);
    
    /**
     * 通信客户端
     */
    private INettyRemotingClient remotingClient;

    
    public TspClientImpl(INettyConfigClient nettyConfig){
        this.remotingClient = new NettyRemotingClient(nettyConfig);
    }
    
    /**
     * 
     * 功能说明:启动
     * 
     */
    public void start() {
        remotingClient.start();
    }
    
    /**
     * 
     * 功能说明:关闭
     * 
     */
    public void shutdown() {
        remotingClient.shutdown();
    }
    
    
    /**
     * 
     * 功能说明:发送心跳
     * 
     * @param serverAddr 服务端地址
     * @param heartbeatData 心跳数据
     * @return 请求结果
     * @throws TspRemotingException 
     */
    public void sendHeartBeat(final String serverAddr, final HeartbeatData heartbeatData) throws TspRemotingException {
        String request = XmlUtil.toXml(heartbeatData);
        RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(RequestCode.HEART_BEAT);
        remotingCommand.setBody(request.getBytes());
        remotingClient.invokeOneway(serverAddr, remotingCommand, null);
    }
    
    /**
     * 
     * 功能说明:
     * 
     * @param serverAddr
     * @param request
     * @param timeoutMillis
     * @param requestCode
     * @return
     */
    public RequestResult requestAsync(String serverAddr, String request, long timeoutMillis, int requestCode){
        RequestResult requestResult = new RequestResult();
        RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(requestCode);
        remotingCommand.setBody(request.getBytes());
        try {
            this.remotingClient.invokeAsync(serverAddr, remotingCommand, timeoutMillis, null, null);
        } catch (TspRemotingException e) {
            switch (e.getExceptionType()) {
                case REQUEST_TIME_OUT:
                    requestResult.setRequestResultType(NettyRequestResult.FAIL);
                    break;
                case REQUEST_SEND_FAIL:
                    requestResult.setRequestResultType(NettyRequestResult.SEND_FAIL);
                    break;
            }
            requestResult.setErrorMessage(e.getMessage());
            LOG.error("TSP-CLIENT: async request to server[{}] body[{}] exception:", serverAddr, request, e);
        }
        return requestResult;
    }
    
    
    /**
     * 
     * 功能说明:
     * 
     * @param serverAddr
     * @param request
     * @param timeoutMillis
     * @param requestCode
     * @return
     */
    public RequestResult requestSync(String serverAddr, String request, long timeoutMillis, int requestCode){
        RemotingCommand reponse = null;
        RequestResult requestResult = new RequestResult();
        RemotingCommand remotingCommand = RemotingCommand.createRequestCommand(requestCode);
        remotingCommand.setBody(request.getBytes());
        try {
            reponse = this.remotingClient.invokeSync(serverAddr, remotingCommand, timeoutMillis);
            assert reponse != null;
            if (ResponseCode.SUCCESS != reponse.getCode()) {
                requestResult.setRequestResultType(NettyRequestResult.FAIL);
                requestResult.setErrorMessage(new String(reponse.getBody()));
            }else{
                requestResult.setBody(new String(reponse.getBody()));
            }
        } catch (TspRemotingException e) {
            switch (e.getExceptionType()) {
                case REQUEST_TIME_OUT:
                    requestResult.setRequestResultType(NettyRequestResult.FAIL);
                    break;
                case REQUEST_SEND_FAIL:
                    requestResult.setRequestResultType(NettyRequestResult.SEND_FAIL);
                    break;
            }
            requestResult.setErrorMessage(e.getMessage());
            LOG.error("TSP-CLIENT: sync request to server[{}] body[{}] exception:", serverAddr, request, e);
        }
        return requestResult;
    }
    
}
